#include <ESP8266WiFi.h>
#include "ELMduino.h"
#include <SoftwareSerial.h>
#include <LedControl.h>
#include <Adafruit_NeoPixel.h>
#include <FastLED.h>
#define PIN D2
#define BRIGHTNESS 20 // 设置灯光亮度
#define ELM_PORT Serial1
int DIN = D5;
int CS =  D6;
int CLK = D7; 
    LedControl lc=LedControl(DIN,CLK,CS,0);
    byte R[8]={0x7E,0x66,0x66,0x7E,0x70,0x7C,0x6E,0x62};/*"R",0*/
    byte kn[8]={0x42,0x62,0x72,0x5A,0x4E,0x46,0x42,0x00};/*"n",0*/
    byte one[8]={0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00};/*"1",0*/
    byte tow[8]={0x7E,0x02,0x02,0x7E,0x40,0x40,0x7E,0x00};/*"2",0*/
    byte sui[8]={0x7E,0x02,0x02,0x3E,0x02,0x02,0x7E,0x00};/*"3",0*/
    byte four[8]={0x08,0x18,0x28,0x48,0x7C,0x08,0x7E,0x00};/*"4",0*/
    byte five[8]={0x7E,0x40,0x40,0x7E,0x02,0x02,0x7E,0x00};/*"5",0*/
    byte six[8]={0x7E,0x40,0x40,0x7E,0x42,0x42,0x7E,0x00};/*"6",0*/
    byte full[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};/*"0",0*/
    byte off[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/*"6",0*/
byte x0[8]={0x00,0x00,0x77,0x55,0x55,0x55,0x77,0x00};/*"0",0*/
    byte x1[8]={0x00,0x00,0x27,0x25,0x25,0x25,0x27,0x00};/*"10",0*/
    byte x2[8]={0x00,0x00,0x77,0x15,0x75,0x45,0x77,0x00};/*"20",0*/
    byte x3[8]={0x00,0x00,0x77,0x15,0x75,0x15,0x77,0x00};/*"30",0*/
    byte x35[8]={0x00,0x00,0x77,0x14,0x77,0x11,0x77,0x00};/*"35",0*/
    byte x4[8]={0x00,0x00,0x27,0x65,0xF5,0x25,0x27,0x00};/*"40",0*/
    byte x5[8]={0x00,0x00,0x77,0x45,0x75,0x15,0x77,0x00};/*"50",0*/
    byte x6[8]={0x00,0x00,0x77,0x45,0x75,0x55,0x77,0x00};/*"60",0*/
    byte x7[8]={0x00,0x00,0x77,0x15,0x15,0x15,0x17,0x00};/*"70",0*/
    byte x8[8]={0x00,0x00,0x77,0x55,0x75,0x55,0x77,0x00};/*"80",0*/
    byte x85[8]={0x00,0x00,0x77,0x54,0x77,0x51,0x77,0x00};/*"85",0*/   
    byte x90[8]={0x00,0x00,0x77,0x55,0x75,0x15,0x77,0x00};/*"90",0*/
    byte x93[8]={0x00,0x00,0x77,0x51,0x77,0x11,0x77,0x00};/*"93",0*/
    byte x95[8]={0x00,0x00,0x77,0x54,0x77,0x11,0x77,0x00};/*"95",0*/
    byte x97[8]={0x00,0x00,0x77,0x51,0x71,0x11,0x71,0x00};/*"97",0*/    
    byte x100[8]={0x00,0x00,0xBF,0xAD,0xAD,0xAD,0xBF,0x00};/*"100",0*/
    byte x105[8]={0x00,0x00,0xBF,0xAC,0xAF,0xA9,0xBF,0x00};/*"105",0*/ 
    byte x107[8]={0x00,0x00,0xBF,0xA9,0xA9,0xA9,0xB9,0x00};/*"107",0*/
    byte x110[8]={0x00,0x00,0xAE,0xAA,0xAA,0xAA,0xAE,0x00};/*"110",0*/
    byte x113[8]={0x00,0x00,0xAE,0xA2,0xAE,0xA2,0xAE,0x00};/*"113",0*/
    byte x115[8]={0x00,0x00,0xAE,0xA8,0xAE,0xA2,0xAE,0x00};/*"115",0*/
    byte x117[8]={0x00,0x00,0xAE,0xA2,0xA2,0xA2,0xA2,0x00};/*"117",0*/
    byte x120[8]={0x00,0x00,0xBF,0x8D,0xBD,0xA5,0xBF,0x00};/*"120",0*/
    byte xfull[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};/*"120",0*/

const char* ssid = "WiFi-OBDII";
const char* password = "your-password";

//IP Adress of your ELM327 Dongle
IPAddress server(192, 168, 0, 10);
WiFiClient client;
ELM327 myELM327;

typedef enum { ENG_RPM,SPEED,COOL} obd_pid_states;
obd_pid_states obd_state = ENG_RPM;
float rpm = 0;
float kph = 0;
int Z = 0; 
int x = 0;
int d = 0;
int cool = 0;
int j;
int i;
#define NUMPIXELS 10//流水灯数量
 
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);





const int ledPin = D3; // LED 连接到 D2 引脚
const int keyPin = D4; // 按键连接到 D4 引脚
 
volatile bool flag = false; // 记录 LED 状态的标志
 
// 外部中断处理函数
ICACHE_RAM_ATTR void handleInterrupt() {
      flag = !flag; // 切换 LED 状态
      delay(20);
}
 
void setup() {
  pixels.begin();
    Serial.begin(230400);
   pixels.setBrightness(BRIGHTNESS); // 设置灯光亮度
  lc.shutdown(0,false);
  lc.setIntensity(0,2);      //调整最大亮度为 15
  lc.clearDisplay(0); 
  int hue = 0; // 初始化色相值

  // 先熄灭所有灯
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, 0); // 关闭所有灯
  }
  pixels.show(); // 显示熄灭效果
  delay(100); // 延迟一段时间

  // 依次点亮彩色渐变循环流水灯
  for (int i = 0; i < NUMPIXELS; i++) {
    int pixelColor = pixels.ColorHSV(hue); // 根据色相值获取彩色
    pixels.setPixelColor(i, pixelColor); // 设置每颗灯的颜色
    hue += 655360/180; // 色相值增加，实现彩色渐变循环
    pixels.show(); // 显示灯光效果
    
    delay(50); // 延迟一段时间
  }
  // Connecting to ELM327 WiFi
  Serial.print("Connecting to ");
  Serial.println(ssid);
  printByte(kn);
  WiFi.mode(WIFI_AP);
  WiFi.begin(ssid);
  // WiFi.begin(ssid, password); //Use this line if your ELM327 has a password protected WiFi

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("Connected to Wifi");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  if (client.connect(server, 35000))
    Serial.println("connected");
  else
  {
    Serial.println("connection failed");
    ESP.reset();
  }
  myELM327.begin(client, true, 2000);
  
  
  pinMode(ledPin, OUTPUT);      // 设置 LED 引脚为输出模式
  pinMode(keyPin, INPUT);// 设置按键引脚为输入模式，并启用上拉电阻
 
  attachInterrupt(digitalPinToInterrupt(keyPin), handleInterrupt, FALLING); // 设置外部中断
}
 
void loop() {
  if (flag) {
    digitalWrite(ledPin, HIGH); // 点亮 LED
    switch (obd_state)
  { 
    case ENG_RPM:
    {
      rpm = myELM327.rpm();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS)
      { 
       Z=rpm/1000;
      for (j = 0; j < Z; j++) {
      if(Z<5){pixels.setPixelColor(j, pixels.Color(Z*40, 210/Z, 0)); // 依次点亮灯
        pixels.show(); // 显示灯光效果
     delay(10);
     }
     else {
      printByte(full);
      pixels.fill(pixels.Color(255, 0, 0), 0, NUMPIXELS);
      pixels.show();
      delay(10); // 等待一段时间
      printByte(off);
      pixels.clear();
      pixels.show();
      delay(10); // 等待一段时间

     }
  }
  
  for (i = 10 - 1; i >= Z; i--) {
    pixels.setPixelColor(i, 0); // 从右往左依次熄灭
    pixels.show(); // 显示灯光效果
    delay(10);
  }
 
       obd_state = SPEED;
      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
      {
        myELM327.printError();
        obd_state = SPEED;
      }
      
      break;
    }
    case SPEED:
    {
      kph = myELM327.kph();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS)
      {
      d = rpm/kph;
    if(d>=110&&d<180)
	{
	  printByte(one);
	}
	else if(d>=52&&d<65)
	{
	     printByte(tow);
	}
	else if(d>=43&&d<52)
	{
		printByte(sui);
	}
	else if(d>=33&&d<41)
	{
	printByte(four);
	}
else if(d>=24&&d<32)
	{
	printByte(five);
	}

else if(d>=10&&d<23)
	{
	printByte(six);
	}
	else{
		printByte(kn);

	}

       obd_state = ENG_RPM;

      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
      {
        myELM327.printError();
        obd_state = ENG_RPM;
      }
      
      break;
    }


}
  } else {
    digitalWrite(ledPin, LOW);  // 关闭 LED
    switch (obd_state)
  { 
    case ENG_RPM:
    {
      rpm = myELM327.rpm();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS)
      { 
       Z=rpm/1000;
      for (j = 0; j < Z; j++) {
      if(Z<5){pixels.setPixelColor(j, pixels.Color(Z*40, 210/Z, 0)); // 依次点亮灯
        pixels.show(); // 显示灯光效果
     delay(10);
     }
     else {
      pixels.fill(pixels.Color(255, 0, 0), 0, NUMPIXELS);
      pixels.show();
      delay(10); // 等待一段时间
      pixels.clear();
      pixels.show();
      delay(10); // 等待一段时间
     }
  }
  
  for (i = 10 - 1; i >= Z; i--) {
    pixels.setPixelColor(i, 0); // 从右往左依次熄灭
    pixels.show(); // 显示灯光效果
    delay(10);
  }
       obd_state = COOL;
      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
      {
        myELM327.printError();
        obd_state = COOL;
      }
      
      break;
    }
    case COOL:
    {
      cool = myELM327.engineCoolantTemp();
      
      if (myELM327.nb_rx_state == ELM_SUCCESS)
      {
      switch(cool){
      case 0:
        printByte(x0);
        break;
      case 10:
       printByte(x1);
       break;
      case 20:
       printByte(x2);
       break;
      case 30:
       printByte(x3);
       break;
      case 35:
       printByte(x35);
       break;
       case 40:
        printByte(x4);
        break;
      case 50:
       printByte(x5);
       break;
      case 60:
       printByte(x6);
       break;
      case 70:
       printByte(x7);
       break;
        case 80:
       printByte(x8);
       break;
        case 85:
       printByte(x85);
       break;
       case 90:
       printByte(x90);
       break;
      case 93:
       printByte(x93);
       break;
      case 95:
       printByte(x95);
       break;
      case 97:
        printByte(x97);
        break;
      case 100:
       printByte(x100);
       break;
      case 105:
       printByte(x105);
       break;
       case 107:
       printByte(x107);
       break;
      case 110:
       printByte(x110);
       break; 
      case 112:
       printByte(xfull);
       delay(10);
      lc.clearDisplay(0); 
       break;
      case 113:
       printByte(x113);
       break;
     case 115:
       printByte(x115);
       break;
      case 117:
       printByte(x117);
       break;
      case 120:
       printByte(x120);
       break;
      }
       obd_state = ENG_RPM;
      }
      else if (myELM327.nb_rx_state != ELM_GETTING_MSG)
      {
        myELM327.printError();
        obd_state = ENG_RPM;
      }
      
      break;
    }
}
  }
}






void printByte(byte character [])
{
  int i = 0;
  for(i=0;i<8;i++)
  {
    lc.setRow(0,i,character[i]);
  }
}

